home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_09_05
/
9n05072a
< prev
next >
Wrap
Text File
|
1991-03-02
|
7KB
|
259 lines
/* soffset and related routines. C/C++. Author: Stephen D. Williams */
/* Structure packing and unpacking routines, with alignment compensation. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h> /* used to set ints to max/min on over/under flow */
#define yr_of_date(d) ((int)((d)/10000L))
#define mo_of_date(d) ((int)(((d)%10000L)/100L))
#define dy_of_date(d) ((int)(((d)%10000L)%100L))
#define date_of_yrmody(y,m,d) ((y)*10000L+(m)*100L+(d))
extern long us_date_to_long(char *dates, char **endptr);//in date.cxx
int *chkalign(void)
{
/* char, short, int, long, float, double, not used: enum, long double */
static int alignarry[8]= {0,0,0,0,0,0,0,0};
/* if you really have a long double, doubles below should change */
struct { double a; char b; char c; } c;
struct { double a; char b; short s; } s;
struct { double a; char b; int i; } i;
struct { double a; char b; long l; } l;
struct { double a; char b; float f; } f;
struct { double a; char b; double d; } d;
/* sets number of pad chars to get to boundary */
alignarry[0]=((char *)&c.c-(char *)&c.b)-1;
alignarry[1]=((char *)&s.s-(char *)&s.b)-1;
alignarry[2]=((char *)&i.i-(char *)&i.b)-1;
alignarry[3]=((char *)&l.l-(char *)&l.b)-1;
alignarry[4]=((char *)&f.f-(char *)&f.b)-1;
alignarry[5]=((char *)&d.d-(char *)&d.b)-1;
return(alignarry);
}
int num_fields(const char *str) /* count non digits/spaces */
{
int nf = 0;
while(*str)
{
if(isdigit(*str++))
continue;
// if(!isspace(*(str-1))) // assume any non digit is valid now
// watch for 2 digit lengths to use this
nf++;
}
return(nf);
}
/* gets the offset of the nth item from 0 */
int soffset(const char *str, int n, char *t, int *numitems, int dat_align)
{ // type/size is "c20"
char *endptr;
int num, size = 0;
int ind;
static int *al = NULL; // only call once
if(!al)
al = chkalign();
while(n--)
{
char cc;
cc = *str++;
num = (int)strtol(str, &endptr, 10);
str = endptr;
num = num ? num : 1;
switch(cc)
{ /* skip char */
case 'c':
case 's':
break;
case 'i':
case 'u':
num *= sizeof(int);
break;
case 'D': /* long date */
case 'l':
case 'm': /* unsigned long */
num *= sizeof(long);
break;
case 'f':
num *= sizeof(float);
break;
case 'd':
num *= sizeof(double);
break;
default:
return(0); /* bad format code */
}
switch(*str)
{ /* look at next char */
case 's':
case 'c':
ind = 0;
break;
case 'i':
case 'u':
ind = 2;
break;
case 'D': /* long date */
case 'l':
case 'm':
ind = 3;
break; /* unsigned long */
case 'f':
ind = 4;
break;
case 'd':
ind = 5;
break;
default:
ind = 0; /* either bad format code, or end of string */
}
size += num; /* add size of current element */
/* this should align to next boundary, if on */
if (dat_align)
size += ((al[ind] + 1 - (al[ind] & size)) & al[ind]);
}
if(t)
*t = *str; /* return type */
str++;
num = (int)strtol(str, &endptr, 10);
str = endptr;
num = num ? num : 1;
if(numitems)
*numitems = num; /* if passed a pointer, return len */
return(size);
}
/* converts the data to str */
// fmt is null or "" for not used
void ttos(char *dest, void *src, int offs, char t, int numitems, char *fmt)
{ /* doesn't check for sprintf overflow */
int fmtp = (fmt && *fmt);
switch(t & 0xff)
{
case 'c': /* this adds a null to end of all strings */
if(fmtp)
{
sprintf(dest, fmt, ((char *)src+offs));
}
else
{
strncpy(dest,((char *)src+offs),numitems);
// dest[numitems] = 0; /* delimit string */
}
break;
case 'i':
sprintf(dest,fmtp ? fmt : "%d",*((int *)((char *)src+offs)));
break;
case 'u':
sprintf(dest,fmtp ? fmt : "%u",*((unsigned *)((char *)src+offs)));
break;
case 'l':
sprintf(dest,fmtp ? fmt : "%ld",*((long *)((char *)src+offs)));
break;
case 'm': /* unsigned long */
sprintf(dest,fmtp ? fmt : "%lu",*((unsigned long *)((char *)src+offs)));
break;
case 'D': /* long date */
{
long t;
t = *((long *)((char *)src+offs));
if((t == 0) || (t == -1))
strcpy(dest, " / / ");
else
{
sprintf(dest,fmtp ? fmt : "%02.2d/%02.2d/%02.2d",
mo_of_date(t), dy_of_date(t), yr_of_date(t));
}
}
break;
case 'f': /* note: prints ieee max significant */
sprintf(dest,fmtp ? fmt : "%.7g", *((float *) ((char *)src+offs)));
break;
case 'd':
sprintf(dest,fmtp ? fmt : "%.15g", *((double *) ((char *)src+offs)));
break;
}
}
/* converts the str to data, returns success: only for special data types */
int stot(void *dest, char *src, int offs, char t, int numitems)
{ /* doesn't check for sprintf overflow */
long ttmp;
char *p;
p = (char *)dest + offs;
switch(t & 0xff)
{
case 'c':
strncpy(p,src,numitems);
break;
case 'i':
*((int *)(p)) = (int)(ttmp = strtol(src, (char **)NULL, 10));
if(ttmp > INT_MAX)
*((int *)p) = INT_MAX;
else
if(ttmp < INT_MIN)
*((int *)p) = INT_MIN;
break;
case 'u':
*((unsigned *)(p)) = (int)(ttmp = strtoul(src, (char **)NULL, 10));
if(ttmp > UINT_MAX)
*((unsigned *)p) = UINT_MAX;
break;
case 'l':
*((long *)(p)) = strtol(src, (char **)NULL, 10);
break;
case 'm': /* unsigned long */
*((unsigned long *)(p)) = strtoul(src, (char **)NULL, 10);
break;
case 'D': /* long date */
*((long *)(p)) = us_date_to_long(src, (char **) 0);
if (*(long *)p == -1l)
return(-1); /* bad date */
break;
case 'f':
*((float *)(p)) = (float)strtod(src, (char **)NULL);
break;
case 'd':
*((double *)(p)) = strtod(src, (char **)NULL);
break;
}
return(0); /* good conversion */
}
int num_chars_display(char type, int numitems)
{
int num = 1;
switch(type & 0xff)
{ /* skip char */
case 'c':
case 's':
num = numitems;
break;
case 'i':
num = 6;
break;
case 'u':
num = 5;
break;
case 'D': /* long date */
num = 8;
break;
case 'l':
num = 11;
break;
case 'm': /* unsigned long */
num = 10;
break;
case 'f':
num = 16;
break;
case 'd':
num = 24;
break;
default:
num = 8; /* bad format code */
}
return(num);
}